package com.yanghui.lingyue.functions.ktBase

import com.icedata.sika.bridge.SikaEvent
import com.icedata.sika.bridge.SikaGroupEvent
import com.icedata.sika.bridge.SikaImageMessage
import com.icedata.sika.bridge.SikaUserEvent
import com.icedata.sika.core.CommandProcessor
import com.icedata.sika.core.Sika
import com.icedata.sika.util.Logger
import com.yanghui.lingyue.bot.Bot
import com.yanghui.lingyue.data.Command
import com.yanghui.lingyue.data.Operation
import com.yanghui.lingyue.functions.AbstractFunction
import com.yanghui.lingyue.utils.functionUtils.FunctionUtils
import com.yanghui.lingyue.utils.netUtils.NetImageUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.awt.image.BufferedImage
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.util.*
import javax.imageio.ImageIO

object LinePicture : AbstractFunction() {
    override val name: String = "LinePic"

    override suspend fun parse(event: SikaEvent, sika: Sika): LinkedList<Command> {
        val command = LinkedList<Command>()
        if (event is SikaUserEvent) return command
        event as SikaGroupEvent
        if (!FunctionUtils.atBot(event)) return command
        if (!FunctionUtils.checkValid(event)) return command
        if (event.sendGroup.id !in enableGroup) return command
        val param = FunctionUtils.extractKeyword(event, "线稿")
        param?.let {
            command.add(Command(event, name, it))
        }
        return command
    }

    override suspend fun execute(command: Command, sika: Sika): CommandProcessor.Result {
        val operation = Operation(command)
        Bot.sikaCore.databaseInsert(operation)
        if (!command.event.message.hasImageMessage) {
            command.sendGroup?.sendMessage("你发送的似乎没有图片")
            return CommandProcessor.Result.ADOPT
        }
        // 提取参数
        var size = 2
        if (command.param.toLowerCase().contains("size:")) {
            try {
                size = command.param.toLowerCase().replace("size:", "").trim().toInt()
                if (size > 5 || size <= 0)
                    throw java.lang.NumberFormatException()
            } catch (e: NumberFormatException) {
                command.sendGroup?.sendMessage("指令似乎有错误哦，请使用size: 大小限制为1-5")
                return CommandProcessor.Result.ADOPT
            }
        }
        // 找到图片
        var imageStream: InputStream? = null
        for (m in command.event.message) {
            if (m is SikaImageMessage) {
                imageStream = NetImageUtils.getImageFromURL(m.getUrl())
            }
        }
        imageStream?.let {
            GlobalScope.launch(Dispatchers.IO) {
                try {
                    val bf: BufferedImage = ImageIO.read(imageStream)
                    // 将图片转换为二维数组
                    val width = bf.width
                    val height = bf.height
                    val rawArray: Array<IntArray> = convertImageToArray(bf)
                    val newArray = Array(height - 2) { IntArray(width - 2) }
                    val kernel = Array(size * 2 + 1) { IntArray(size * 2 + 1) }
                    convolve(rawArray, newArray, kernel)
                    writeImageFromArray("C:\\${command.sendGroup?.id}.png", "png", newArray)
                    command.sendGroup?.let {
                        val m = SikaImageMessage.build(
                            File("C:\\${command.sendGroup?.id}.png"),
                            it,
                            SikaImageMessage.PNG
                        )
                        it.sendMessage(m)
                    }
                } catch (e: Exception) {
                    Logger.logError(e)
                }
            }
        }
        return CommandProcessor.Result.ADOPT
    }

    private fun convertImageToArray(bf: BufferedImage): Array<IntArray> {
        // 获取图片宽度和高度
        val width = bf.width
        val height = bf.height
        // 将图片sRGB数据写入一维数组
        val data = IntArray(width * height)
        bf.getRGB(0, 0, width, height, data, 0, width)
        // 将一维数组转换为为二维数组
        val rgbArray = Array(height) { IntArray(width) }
        for (i in 0 until height) if (width >= 0) System.arraycopy(data, i * width, rgbArray[i], 0, width)
        return rgbArray
    }

    private fun convolve(rawArray: Array<IntArray>, newArray: Array<IntArray>, kernel: Array<IntArray>) {
        val kernelHeight = kernel.size
        val kernelWidth: Int = kernel[0].size
        val pictureHeight = rawArray.size
        val pictureWidth: Int = rawArray[0].size
        val r = (kernelHeight - 1) / 2
        //整张图片黑白化
        for (j in 0 until pictureHeight) {
            for (i in 0 until pictureWidth) {
                rawArray[j][i] = rgbToGray(rawArray[j][i])
            }
        }
        for (j in 0 until pictureHeight - kernelHeight + 1) {
            for (i in 0 until pictureWidth - kernelWidth + 1) {
                val rawColor = rawArray[j + r][i + r]
                //找到最大值
                var maxColor = 0
                for (m in 0 until kernelHeight) {
                    for (n in 0 until kernelWidth) {
                        if (rawArray[j + m][i + n] > maxColor) {
                            maxColor = rawArray[j + m][i + n]
                        }
                    }
                }
                //反色
                maxColor = 255 - maxColor
                //颜色减淡
                val newColor: Int = if (rawColor == 255 || maxColor == 255) {
                    255
                } else {
                    (rawColor / (1.0 - maxColor / 255.0)).toInt()
                }
                newArray[j][i] = grayToRgb(ctrlLim(newColor))
            }
        }
    }

    private fun rgbToGray(color: Int): Int {
        val red = color and 0x00FF0000 shr 16
        val green = color and 0x0000FF00 shr 8
        val blue = color and 0x000000FF
        return (red + green + blue) / 3
    }

    private fun grayToRgb(color: Int): Int {
        return color * (65536 + 256 + 1)
    }

    private fun ctrlLim(num: Int): Int {
        if (num > 255) {
            return 255
        }
        return if (num < 0) {
            0
        } else num
    }

    private fun writeImageFromArray(imageFile: String, type: String, rgbArray: Array<IntArray>) {
        // 获取数组宽度和高度
        val width: Int = rgbArray[0].size
        val height = rgbArray.size
        // 将二维数组转换为一维数组
        val data = IntArray(width * height)
        for (i in 0 until height) System.arraycopy(rgbArray[i], 0, data, i * width, width)
        // 将数据写入BufferedImage
        val bf = BufferedImage(width, height, BufferedImage.TYPE_INT_BGR)
        bf.setRGB(0, 0, width, height, data, 0, width)
        // 输出图片
        try {
            val file = File(imageFile)
            ImageIO.write(bf, type, file)
        } catch (e: IOException) {
            Logger.logError(e)
        }
    }
}